/*
 * No copyright. Use and modify as desired - even claim you created this
 * project! Please just email me with suggestions, corrections or best
 * practices that I should've known about: dev.kyle.watson@gmail.com. One of
 * the best parts of programming is learning, after all.
 * 
 * See kwitter/index.html for usage examples.
 */
(function( $ ) {

	// print error to console
	var fatal = function( msg ) {
		window.console && console.error && console.error(msg);
	},

	// log message to console
	debug = function( msg ) {
		window.console && console.log && console.log(msg);
	},

	// Twitter search URL
	searchUrl = 'http://search.twitter.com/search.json',

	// capture URLs
	re_links = /(\b(https?|ftp):\/\/([\w-+&@#\/%?=~|!:,.;]*[\w-+&@#\/%=~|]))/g,

	// capture users (prefixed with the @ symbol)
	re_users = /[\@]+([\w-]+)/g,

	// capture hashtags (prefixed with the # symbol)
	re_hashtags = /[\#]+([\w-]+)/g,

	// global copy of $(this)
	$this,

	// interval id from setInterval
	_iref,

	// default settings
	settings = {
		maxTweets : 20,
		refreshInterval : undefined,
		loadingMessage : 'Loading...',
		filter : {
			to : [],
			from : [],
			text : []
		},
		fromUsers : [],
		toUsers : [],
		phrases : [],
		useStyle : false,
		cssFile : 'js/default.css'
	},

	_kwitter = {

		loadDefaultCss : function() {
			if (settings.cssFile && $( '#kwitter-style' ).length == 0) {
				$( document.createElement('link') )
						.attr('id', 'kwitter-style')
						.attr('rel', 'stylesheet')
						.attr('type', 'text/css')
						.attr('href', settings.cssFile)
						.appendTo('head');
			}
		},

		buildQuery : function() {
			var data = [],
			add = function( setting, key ) {
				key = typeof (key) != 'undefined' ? key : '';
				var d = [];
				if (setting.length) {
					for ( var i = 0; i < setting.length; i++) {
						d.push(key + setting[i]);
					}
					data.push(d.join(' OR '));
				}
			};

			add(settings.fromUsers, 'from:');
			add(settings.toUsers, 'to:');
			add(settings.phrases);

			return data.join(' OR ');
		},

		buildFromLink : function( result ) {
			return ('http://www.twitter.com/' + result.from_user);
		},

		buildMessage : function( result ) {
			var html = [],
				fromLink = _kwitter.buildFromLink(result),
				from = result.from_user,
				imgLink = result.profile_image_url,
				text = _kwitter.linkify(result.text),
				timestamp = result.created_at;

			html.push('<div class="kweet">');
			html.push('<div class="kweet-image">');
			html.push('<a href="', fromLink, '" class="twitter-profile-link">');
			html.push('<img alt="', from, '" src="', imgLink, '" />');
			html.push('</a>');
			html.push('</div>');
			html.push('<div class="kweet-content">');
			html.push('<div class="kweet-content-row">');
			html.push('<span class="kweet-username">');
			html.push('<a href="', fromLink, '" class="twitter-screen-name twitter-profile-link">', from, '</a>');
			html.push('</span>');
			html.push('</div>');
			html.push('<div class="kweet-content-row">');
			html.push('<div class="kweet-text">', text, '</div>');
			html.push('</div>');
			html.push('<div class="kweet-content-row">');
			html.push('<span class="kweet-timestamp">', timestamp, '</span>');
			html.push('</div>');
			html.push('</div>');
			html.push('</div>');

			return html.join('');
		},

		// TODO - faster to 
		isValid : function( result ) {
			var filter = settings.filter,
			valid = function( filter, param ) {
				if (filter && filter.length) {
					for (var i = 0; i < filter.length; i++) {
						if (param && param.match(new RegExp(filter, 'i'))) {
							return false;
						}
					}
				}
				return true;
			};

			return (valid(filter.to, result.to_user)
					&& valid(filter.from, result.from_user)
					&& valid(filter.text, result.text));
		},

		linkify : function( text ) {
			text = text.replace(re_links, '<a href="$1" class="url-external">$3</a>');
			text = text.replace(re_users, '<a href="http://www.twitter.com/$1" class="url-user">@$1</a>');
			text = text.replace(re_hashtags,'<a href="#" style="cursor:pointer" class="url-hashtag">#$1</a>');
			return text;
		},

		stopRefresh : function() {
			if (_iref) {
				clearInterval(_iref);
				_iref = undefined;
			}
		},

		startRefresh : function() {
			_kwitter.stopRefresh();
			var refInt = settings.refreshInterval;
			if (refInt && !isNaN(refInt) && refInt > 1000) {
				_iref = setInterval(_kwitter.loadTweets, settings.refreshInterval);
			}
		},

		loadTweets : function() {
			debug('loading Tweets');
			if (settings.loadingMessage) {
				$this.html(settings.loadingMessage);
			}

			var query = _kwitter.buildQuery();
			$.ajax({
				url : searchUrl,
				type : 'GET',
				dataType : 'jsonp',
				timeout : 1000,
				data : {
					q : query,
					rpp : settings.maxTweets
				},
				error : function() {
					$this.html('unable to load tweets');
				},
				success : function( json ) {
					$this.empty();

					$.each(json.results, function( i, result ) {
						if (_kwitter.isValid(result)) {
							if (result.text && result.text != 'undefined') {
								var tweetHtml = _kwitter.buildMessage(result);
								$( tweetHtml )
										.hide()
										.appendTo($this)
										.show('slow');
							}
						}
					});

					$( '.url-hashtag', $this).click(function() {
						var hashtag = $( this ).text();
						hashtag = hashtag.substring(1);
						_kwitter.stopRefresh();
						methods.reload({fromUsers : [], toUsers : [], phrases : [ hashtag ]});
						return false;
					});
				}
			});
		}
	},

	// plugin methods
	methods = {

		init : function( options ) {
			debug('init called');
			if (options) {
				$.extend(settings, options);
			}
			if (settings.useStyle) {
				_kwitter.loadDefaultCss();
			}
			_kwitter.loadTweets();
			_kwitter.startRefresh();
			return this;
		},

		reload : function( options ) {
			debug('reload called');
			if (options) {
				$.extend(settings, options);
			}
			_kwitter.loadTweets();
			return this;
		},

		startInterval : function() {
			debug('startInterval called');
			_kwitter.startRefresh();
			return this;
		},

		stopInterval : function() {
			debug('stopInterval called');
			_kwitter.stopRefresh();
			return this;
		}
	};

	$.fn.kwitter = function( method ) {
		$this = this;
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			fatal('Method ' + method + ' does not exist on jQuery.kwitter');
			return this;
		}
	};

})(jQuery);